#include "precomp.h"
#include "EntityLogic.h"

#include "../Entity.h"

#include "../Goals/GoalThink.h"

namespace Tmpl {

#define LOGIC_JOBS 8

static DataValuePool<EntityLogic> gLogics;

// EntityLogicSystem setup functions
void EntityLogicSystem::Init()
{
	gLogics.Init();
}
void EntityLogicSystem::Clear()
{
	gLogics.Clear();
}
int EntityLogicSystem::NewLogic(Entity* owner)
{
	int id = gLogics.NewValue();

	EntityLogic* value = gLogics.GetValue(id);
	value->mOwner = owner;
	value->mGoals = new GoalThink(owner);

	return id;
}
void EntityLogicSystem::RemoveLogic(int id)
{
	EntityLogic* value = gLogics.GetValue(id);
	delete value->mGoals; value->mGoals = 0;
	gLogics.RemoveValue(id);
}
EntityLogic* EntityLogicSystem::GetLogic(int id)
{
	return gLogics.GetValue(id);
}
// EntityLogic
void EntityLogic::Render() const
{
	mGoals->Render();
}
bool EntityLogic::HandleMessage(const MsgData& msg)
{
	return mGoals->HandleMessage(msg);
}

// Updating
void EntityLogicSystem::UpdateLogicChunk(int chunk)
{
	int count = gLogics.GetValueCount();
	int step = count / LOGIC_JOBS;
	int from = step * chunk;
	int to = ((chunk==LOGIC_JOBS-1) ? count : step * (chunk+1));
	for (int i=from; i<to; ++i)
	{
		EntityLogic* v = gLogics.GetUnmappedValue(i);
		Entity* ent = v->mOwner;

		// Execute Goals
		v->mGoals->Process(chunk);
	}
}
JobHandle EntityLogicSystem::Update(JobHandle dependency)
{
	// Split the stat update chunk in equal parts
	JobHandle logicUpdate = JobManager::NewJob();
	for (int i=0; i<LOGIC_JOBS; ++i)
	{
		JobHandle job = JobManager::NewJob(&EntityLogicSystem::UpdateLogicChunk,i);
		JobManager::AddJobDependency(job, dependency);
		JobManager::AddExecuteJob(job);

		// add this job to the final job
		JobManager::AddJobDependency(logicUpdate, job);
	}
	JobManager::AddExecuteJob(logicUpdate);

	return logicUpdate;
}
}